home *** CD-ROM | disk | FTP | other *** search
/ QRZ! Ham Radio 8 / QRZ Ham Radio Callsign Database - Volume 8.iso / mac / files / t_sys5 / 92052tar.gz / 920528.tar / cmdparse.c < prev    next >
C/C++ Source or Header  |  1992-05-14  |  7KB  |  393 lines

  1. /* @(#) $Header: cmdparse.c,v 1.6 92/05/14 13:19:48 deyke Exp $ */
  2.  
  3. /* Parse command line, set up command arguments Unix-style, and call function.
  4.  * Note: argument is modified (delimiters are overwritten with nulls)
  5.  *
  6.  * Copyright 1991 Phil Karn, KA9Q
  7.  *
  8.  * Improved error handling by Brian Boesch of Stanford University
  9.  * Feb '91 - Bill Simpson
  10.  *              bit16cmd for PPP
  11.  * Mar '91 - Glenn McGregor
  12.  *              handle string escaped sequences
  13.  */
  14. #include <ctype.h>
  15. #include <stdio.h>
  16. #include <string.h>
  17. #include "global.h"
  18. #include "proc.h"
  19. #include "cmdparse.h"
  20.  
  21. struct boolcmd {
  22.     char *str;      /* Token */
  23.     int val;        /* Value */
  24. };
  25.  
  26. static struct boolcmd Boolcmds[] = {
  27.     "y",            1,      /* Synonyms for "true" */
  28.     "yes",          1,
  29.     "true",         1,
  30.     "on",           1,
  31.     "1",            1,
  32.     "set",          1,
  33.     "enable",       1,
  34.  
  35.     "n",            0,      /* Synonyms for "false" */
  36.     "no",           0,
  37.     "false",        0,
  38.     "off",          0,
  39.     "0",            0,
  40.     "clear",        0,
  41.     "disable",      0,
  42.     NULLCHAR
  43. };
  44.  
  45. static int print_help __ARGS((struct cmds *cmdp));
  46. static char *stringparse __ARGS((char *line));
  47.  
  48. static char *
  49. stringparse(line)
  50. char *line;
  51. {
  52.     register char *cp = line;
  53.     unsigned long num;
  54.  
  55.     while ( *line != '\0' && *line != '\"' ) {
  56.         if ( *line == '\\' ) {
  57.             line++;
  58.             switch ( *line++ ) {
  59.             case 'n':
  60.                 *cp++ = '\n';
  61.                 break;
  62.             case 't':
  63.                 *cp++ = '\t';
  64.                 break;
  65.             case 'v':
  66.                 *cp++ = '\v';
  67.                 break;
  68.             case 'b':
  69.                 *cp++ = '\b';
  70.                 break;
  71.             case 'r':
  72.                 *cp++ = '\r';
  73.                 break;
  74.             case 'f':
  75.                 *cp++ = '\f';
  76.                 break;
  77. #if defined(__STDC__)
  78.             case 'a':
  79.                 *cp++ = '\a';
  80.                 break;
  81. #endif
  82.             case '\\':
  83.                 *cp++ = '\\';
  84.                 break;
  85. #if defined(__STDC__)
  86.             case '\?':
  87.                 *cp++ = '\?';
  88.                 break;
  89. #endif
  90.             case '\'':
  91.                 *cp++ = '\'';
  92.                 break;
  93.             case '\"':
  94.                 *cp++ = '\"';
  95.                 break;
  96.             case 'x':
  97.                 num = strtoul( --line, &line, 16 );
  98.                 *cp++ = (char) num;
  99.                 break;
  100.             case '0':
  101.             case '1':
  102.             case '2':
  103.             case '3':
  104.             case '4':
  105.             case '5':
  106.             case '6':
  107.             case '7':
  108.                 num = strtoul( --line, &line, 8 );
  109.                 *cp++ = (char) num;
  110.                 break;
  111.             case '\0':
  112.                 return NULLCHAR;
  113.             default:
  114.                 *cp++ = *(line - 1);
  115.                 break;
  116.             };
  117.         } else {
  118.             *cp++ = *line++;
  119.         }
  120.     }
  121.  
  122.     if ( *line == '\"' )
  123.         line++;         /* skip final quote */
  124.     *cp = '\0';             /* terminate string */
  125.     return line;
  126. }
  127.  
  128. int
  129. cmdparse(cmds,line,p)
  130. struct cmds cmds[];
  131. register char *line;
  132. void *p;
  133. {
  134.     struct cmds *cmdp;
  135.     char *argv[NARG];
  136.     int argc;
  137.  
  138.     /* Remove cr/lf */
  139.     rip(line);
  140.  
  141.     for(argc = 0;argc < NARG;argc++)
  142.         argv[argc] = NULLCHAR;
  143.  
  144.     for(argc = 0;argc < NARG;){
  145.         register int qflag = FALSE;
  146.  
  147.         /* Skip leading white space */
  148.         while(isspace(uchar(*line)))
  149.             line++;
  150.         if(*line == '\0')
  151.             break;
  152.         /* '#' is start of comment */
  153.         if(*line == '#')
  154.             break;
  155.         /* Check for quoted token */
  156.         if(*line == '"'){
  157.             line++; /* Suppress quote */
  158.             qflag = TRUE;
  159.         }
  160.         argv[argc++] = line;    /* Beginning of token */
  161.  
  162.         if(qflag){
  163.             /* Find terminating delimiter */
  164.             if((line = stringparse(line)) == NULLCHAR){
  165.                 return -1;
  166.             }
  167.         } else {
  168.             /* Find space or tab. If not present,
  169.              * then we've already found the last
  170.              * token.
  171.              */
  172.             while(*line && !isspace(uchar(*line)))
  173.                 line++;
  174.         }
  175.         if(*line)
  176.             *line++ = '\0';
  177.     }
  178.     if (argc < 1) {         /* empty command line */
  179.         argc = 1;
  180.         argv[0] = "";
  181.     }
  182.     if (argv[0][0] == '?') return print_help(cmds);
  183.     /* Look up command in table; prefix matches are OK */
  184.     for(cmdp = cmds;cmdp->name != NULLCHAR;cmdp++){
  185.         if(strncmp(argv[0],cmdp->name,strlen(argv[0])) == 0)
  186.             break;
  187.     }
  188.     if(cmdp->name == NULLCHAR) {
  189.         if(cmdp->argc_errmsg != NULLCHAR)
  190.             printf("%s\n",cmdp->argc_errmsg);
  191.         return -1;
  192.     } else {
  193.         argv[0] = cmdp->name;
  194.         if(argc < cmdp->argcmin) {
  195.             /* Insufficient arguments */
  196.             printf("Usage: %s\n",cmdp->argc_errmsg);
  197.             return -1;
  198.         } else {
  199.                 return (*cmdp->func)(argc,argv,p);
  200.         }
  201.     }
  202. }
  203.  
  204. /* Call a subcommand based on the first token in an already-parsed line */
  205. int
  206. subcmd(tab,argc,argv,p)
  207. struct cmds tab[];
  208. int argc;
  209. char *argv[];
  210. void *p;
  211. {
  212.     register struct cmds *cmdp;
  213.     int found = 0;
  214.  
  215.     /* Strip off first token and pass rest of line to subcommand */
  216.     if (argc < 2) {
  217.         if (argc < 1)
  218.             printf("SUBCMD - Don't know what to do?\n");
  219.         else {
  220.             printf("\"%s\" subcommands:\n", argv[0]);
  221.             print_help(tab);
  222.         }
  223.         return -1;
  224.     }
  225.     argc--;
  226.     argv++;
  227.     for(cmdp = tab;cmdp->name != NULLCHAR;cmdp++){
  228.         if(strncmp(argv[0],cmdp->name,strlen(argv[0])) == 0){
  229.             found = 1;
  230.             break;
  231.         }
  232.     }
  233.     if(!found){
  234.         printf("\"%s\" subcommands:\n", argv[-1]);
  235.         print_help(tab);
  236.         return -1;
  237.     }
  238.     argv[0] = cmdp->name;
  239.     if(argc < cmdp->argcmin){
  240.         if(cmdp->argc_errmsg != NULLCHAR)
  241.             printf("Usage: %s\n",cmdp->argc_errmsg);
  242.         return -1;
  243.     }
  244.         return (*cmdp->func)(argc,argv,p);
  245. }
  246.  
  247. static int print_help(cmdp)
  248. register struct cmds *cmdp;
  249. {
  250.     register int  i;
  251.  
  252.     for (i = 0; cmdp->name; cmdp++, i++)
  253.         printf((i % 5) < 4 ? "%-16s" : "%s\n", cmdp->name);
  254.     if (i % 5) putchar('\n');
  255.     putchar('\n');
  256.     return 0;
  257. }
  258.  
  259. /* Subroutine for setting and displaying boolean flags */
  260. int
  261. setbool(var,label,argc,argv)
  262. int *var;
  263. char *label;
  264. int argc;
  265. char *argv[];
  266. {
  267.     struct boolcmd *bc;
  268.  
  269.     if(argc < 2){
  270.         printf("%s: %s\n",label,*var ? "on":"off");
  271.         return 0;
  272.     }
  273.     for(bc = Boolcmds;bc->str != NULLCHAR;bc++){
  274.         if(stricmp(argv[1],bc->str) == 0){
  275.             *var = bc->val;
  276.             return 0;
  277.         }
  278.     }
  279.     printf("Valid options:");
  280.     for(bc = Boolcmds;bc->str != NULLCHAR;bc++)
  281.         if(printf(" %s",bc->str) == EOF)
  282.             return 1;
  283.     printf("\n");
  284.     return 1;
  285. }
  286.  
  287. /* Subroutine for setting and displaying bit values */
  288. int
  289. bit16cmd(bits,mask,label,argc,argv)
  290. int16 *bits;
  291. int16 mask;
  292. char *label;
  293. int argc;
  294. char *argv[];
  295. {
  296.     int doing = (*bits & mask);
  297.     int result = setbool( &doing, label, argc, argv );
  298.  
  299.     if ( !result ) {
  300.         if ( doing )
  301.             *bits |= mask;
  302.         else
  303.             *bits &= ~mask;
  304.     }
  305.     return result;
  306. }
  307.  
  308. /* Subroutine for setting and displaying long variables */
  309. int
  310. setlong(var,label,argc,argv)
  311. int32 *var;
  312. char *label;
  313. int argc;
  314. char *argv[];
  315. {
  316.     if(argc < 2)
  317.         printf("%s: %ld\n",label,*var);
  318.     else
  319.         *var = atol(argv[1]);
  320.  
  321.     return 0;
  322. }
  323. /* Subroutine for setting and displaying short variables */
  324. int
  325. setshort(var,label,argc,argv)
  326. unsigned short *var;
  327. char *label;
  328. int argc;
  329. char *argv[];
  330. {
  331.     if(argc < 2)
  332.         printf("%s: %u\n",label,*var);
  333.     else
  334.         *var = atoi(argv[1]);
  335.  
  336.     return 0;
  337. }
  338. /* Subroutine for setting and displaying integer variables */
  339. int
  340. setint(var,label,argc,argv)
  341. int *var;
  342. char *label;
  343. int argc;
  344. char *argv[];
  345. {
  346.     if(argc < 2)
  347.         printf("%s: %i\n",label,*var);
  348.     else
  349.         *var = atoi(argv[1]);
  350.  
  351.     return 0;
  352. }
  353.  
  354. /* Subroutine for setting and displaying unsigned integer variables */
  355. int
  356. setuns(var,label,argc,argv)
  357. unsigned *var;
  358. char *label;
  359. int argc;
  360. char *argv[];
  361. {
  362.     if(argc < 2)
  363.         printf("%s: %u\n",label,*var);
  364.     else
  365.         *var = atoi(argv[1]);
  366.  
  367.     return 0;
  368. }
  369.  
  370. /* Subroutine for setting and displaying int variables (with range check) */
  371.  
  372. int  setintrc(var, label, argc, argv, minval, maxval)
  373. int  *var;
  374. char  *label;
  375. int  argc;
  376. char  *argv[];
  377. int  minval;
  378. int  maxval;
  379. {
  380.   if (argc < 2)
  381.     printf("%s: %i\n", label, *var);
  382.   else {
  383.     int  tmp = atoi(argv[1]);
  384.     if (tmp < minval || tmp > maxval) {
  385.       printf("%s must be %i..%i\n", label, minval, maxval);
  386.       return 1;
  387.     }
  388.     *var = tmp;
  389.   }
  390.   return 0;
  391. }
  392.  
  393.